package com.dries.security.browser.config;

import com.dries.security.core.authentication.mobile.SmsCodeAuthenticationSecurityConfig;
import com.dries.security.core.authorize.AuthorizeConfigManager;
import com.dries.security.core.config.FormAuthenticationConfig;
import com.dries.security.core.properties.SecurityCoreProperties;
import com.dries.security.core.validate.code.ValidateCodeSecurityConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.session.InvalidSessionStrategy;
import org.springframework.security.web.session.SessionInformationExpiredStrategy;
import org.springframework.social.security.SpringSocialConfigurer;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * @Description:
 * @Author ZSY
 * @createTime 2020/9/2 17:58
 */
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private DataSource dataSource;
    @Resource
    public SecurityCoreProperties coreProperties;
    @Resource
    private UserDetailsService userDetailsService;
    @Resource
    private SmsCodeAuthenticationSecurityConfig smsCodeAuthenticationSecurityConfig;
    @Resource
    private ValidateCodeSecurityConfig validateCodeSecurityConfig;
    @Resource
    private SpringSocialConfigurer driesSpringSocialConfig;
    @Resource
    private SessionInformationExpiredStrategy sessionInformationExpiredStrategy;
    @Resource
    private InvalidSessionStrategy invalidSessionStrategy;
    @Resource
    private LogoutSuccessHandler logoutSuccessHandler;
    @Resource
    private FormAuthenticationConfig formAuthenticationConfig;
    @Resource
    private AuthorizeConfigManager authorizeConfigManager;

    /**
     * 添加记住我 功能
     * @return
     */
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        // 第一次自动生成登录表
        // tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        formAuthenticationConfig.configure(http);
        http.apply(validateCodeSecurityConfig)
                .and()
                    .apply(smsCodeAuthenticationSecurityConfig)
                .and()
                    .apply(driesSpringSocialConfig)
                .and()
                // 记住我配置
                .rememberMe()
                    .tokenRepository(persistentTokenRepository())
                    .tokenValiditySeconds(coreProperties.getBrowser().getRememberMeSeconds())
                    .userDetailsService(userDetailsService)
                .and()
                .sessionManagement()
                    // .invalidSessionUrl(SecurityCoreConstants.DEFAULT_SESSION_INVALID_URL)  // 设置session失效跳转地址
                    .invalidSessionStrategy(invalidSessionStrategy)
                    // 设置最大登录用户
                    .maximumSessions(coreProperties.getBrowser().getSession().getMaximumSessions())
                    // 达到最大session时是否阻止新的登录请求
                    .maxSessionsPreventsLogin(coreProperties.getBrowser().getSession().isMaxSessionsPreventsLogin())
                    .expiredSessionStrategy(sessionInformationExpiredStrategy)
                .and()
                .and()
                .logout()
                    .logoutUrl(coreProperties.getBrowser().getLogoutPage())
                    .logoutSuccessHandler(logoutSuccessHandler)
                    .deleteCookies("JSESSIONID")
        .and().csrf().disable();

        authorizeConfigManager.config(http.authorizeRequests());
    }

}
